/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "布局描述.h"
#include "底层绘图/intern/Vulkan/Vulkan框架.h"
#include "底层绘图/intern/Vulkan/buffer/Vk缓存.h"





Inline uint32 f_vk_get参数布局着色阶段(uint32 缓存类型) {
	uint32 ShaderStageFlags = 0;
	if (E_着色阶段::e_顶点着色 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
	}
	if (E_着色阶段::e_细分控制着色 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
	}
	if (E_着色阶段::e_细分着色 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
	}
	if (E_着色阶段::e_几何着色 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
	}
	if (E_着色阶段::e_像素着色 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_FRAGMENT_BIT;
	}
	if (E_着色阶段::e_计算着色 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_COMPUTE_BIT;
	}
	if (E_着色阶段::e_光追射线生成 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_RAYGEN_BIT_KHR;
	}
	if (E_着色阶段::e_光追忽略相交 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_MISS_BIT_KHR;
	}
	if (E_着色阶段::e_光追最近相交 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
	}
	if (E_着色阶段::e_光追回调 & 缓存类型) {
		ShaderStageFlags |= VK_SHADER_STAGE_CALLABLE_BIT_KHR;
	}
	return ShaderStageFlags;
}

struct S_Vk着色器创建参数 : public S_线管创建配置 {

	S_Vk着色器创建参数(const S_线管创建配置& obj) {
		m_参数布局 = obj.m_参数布局;
		m_顶点配置 = obj.m_顶点配置;
	}

	uint32 f_get参数数量() {
		return m_参数布局.size();
	}
	uint32 f_get输入数量() {
		return m_顶点配置.size();
	}


	uint32 f_get着色阶段(uint32 id);
	uint32 f_get参数类型(uint32 id);


	uint32 f_get输入顶点类型(uint32 id) {
		//return VK_VERTEX_INPUT_RATE_INSTANCE;
		return VK_VERTEX_INPUT_RATE_VERTEX;
	}

	uint32 f_get输入顶点排列格式(uint32 id) {
		return VK_FORMAT_R32G32B32_SFLOAT;
	}

	uint32 f_get输入顶点间隔(uint32 id) {
		return m_顶点配置[id].m_元素大小;
	}
};








typedef struct {
	E_着色阶段						m_Type;
	//VkShaderModule					m_Shader;
	//VkPipelineShaderStageCreateInfo	m_着色阶段创建信息;
	VkStridedDeviceAddressRegionKHR	m_跨度设备指针;
	S_板载缓存*						m_着色绑定列表;

}S_Vk着色器;







struct S_Vk着色 : public S_着色 {
	VkDevice					m_设备;
	uint32						m_描述池大小;


	std::vector<S_Vk着色器>							m_光追着色器;
	vector<VkPipelineShaderStageCreateInfo>			m_着色阶段创建信息;
	vector<VkRayTracingShaderGroupCreateInfoKHR>	m_光追着色组创建信息;

	vector<VkStridedDeviceAddressRegionKHR>	m_光追材质绑定列表;


	std::vector<VkDescriptorSetLayout>		m_参数布局;
	VkDescriptorPool						m_参数池;
	VkPipelineLayout						m_线管布局;


	std::vector<VkDescriptorSet>			m_描述集列表;
	VkDescriptorSetAllocateInfo				m_描述集列表分配信息;


	std::vector<VkVertexInputBindingDescription>	m_顶点绑定信息;
	std::vector<VkVertexInputAttributeDescription>	m_管线的顶点输入属性描述;
	VkPipelineVertexInputStateCreateInfo			m_线管顶点输入状态创建信息;




	S_Vk着色(VkDevice& 设备, uint32 阶段数量, std::string name);
	~S_Vk着色();



	//void f_build着色参数布局(uint32 描述集数量);
	void f_init着色参数布局(const S_线管创建配置& 参数配置);
	void f_initRT着色参数布局(const S_线管创建配置& 参数配置);
	void f_alloc参数设置(S_结构对象指针* 描述集列表);
	void f_free参数设置(S_结构对象指针* 描述集列表);


	//std::vector<VkPipelineShaderStageCreateInfo>	f_取着色阶段创建信息();

	void	f_从文件载入着色器(std::string path, E_着色阶段 阶段, uint8 id, bool 光追着色创建 = false);

	//vector<uint32>		f_GLSL_TO_SPV();
	//void	f_销毁着色器(uint32 id);
	//void	f_销毁材质回调();
private:
	void f_create布局描述设置(const S_线管创建配置& 参数配置);

};




void f_shader_create绑定列表();

Inline uint32 f_shader_着色组对齐大小(uint32 勾柄大小, uint32 对齐) {
	return (勾柄大小 + 对齐 - 1) & ~(对齐 - 1);
}

Inline VkStridedDeviceAddressRegionKHR f_shader_get着色绑定列表跨度设备地址(S_VkArray缓存* buf, uint32 对齐大小, uint32 size, uint32 bufOffset) {
	VkStridedDeviceAddressRegionKHR stridedDeviceAddressRegionKHR{};
	stridedDeviceAddressRegionKHR.deviceAddress = f_buf_getAddress(buf) + bufOffset;
	stridedDeviceAddressRegionKHR.stride = 对齐大小;
	//stridedDeviceAddressRegionKHR.stride = 对齐大小 * 着色器数量;
	//stridedDeviceAddressRegionKHR.stride = 0;
	stridedDeviceAddressRegionKHR.size = size;
	
	return stridedDeviceAddressRegionKHR;
}

void f_vkShader_创建着色器(S_Vk着色* shader, std::string path, E_着色阶段 阶段, uint32 id, bool 光追着色创建, uint32 着色ID);
void f_vkShader_销毁着色器(S_Vk着色* shader, uint32 id, bool 光追着色创建);

